package prototype;

class TestA implements Cloneable{
    public int a = 1;
    public Object clone() throws CloneNotSupportedException{
        return super.clone();
    }
}

/**
 * 拷贝相当于直接从内存里面考出来一份
 * String 是引用类型为什么深克隆不需要重新new它？
 * 因为String在常量池里面
 * 每次重新赋值的时候其实是切换常量池对应常量的地址并非地址对应的内容。如果没有对应
 * 常量就创建并返回地址。 注意这个改的是地址不是地址对应内容。
 * new String("abc") abc还是常量池里面内容
 * 但是如果是 new 放到对象是需要深拷贝的。
 *
 * 总结
 * 1、java 自带prototype
 * 2、需要实现cloneable
 * 3、需要重写clone
 * clone 一个新对象不比new一个更快，只不过是省了很多操作步骤。
 * 比如要实例化很多参数 clone 通常更方便。
 * 了解深克隆和浅克隆
 *
 * 深克隆注意
 * 子类对象需要实现cloneable
 * 并且父对象要clone返回克隆的对象以及子对象。
 */
class Cp implements Cloneable{ // 标记型接口,这里必须写，因为运行的时候会做检查。
    public int b = 1;
    TestA testA = new TestA();

    public Object clone() throws CloneNotSupportedException{ // 必须重写
        Cp cpr = (Cp)super.clone();
        cpr.testA = (TestA) testA.clone();

        return cpr;
        // return super.clone(); // 调用父类的构造并且返回。
    }
}



public class prototype {
    public static void main(String args[]){
        System.out.println("prototype");

        Cp cpa = new Cp();

        try {
            Cp cpb =  (Cp)cpa.clone();
            cpa.testA.a = 123; // 当通过父类直接拷贝就是浅复制。如果深拷贝内部对象也需要重写clone，并且需要在Cp克隆的时候在克隆内部对象
            System.out.println(cpa.testA.a);
            System.out.println(cpb.testA.a);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}
